package org.pac4j.vertx.core.store;
import io.vertx.rxjava.core.Vertx;
import io.vertx.rxjava.core.shareddata.AsyncMap;
import org.pac4j.core.exception.TechnicalException;
import org.pac4j.core.store.Store;
import rx.Observable;
import rx.functions.Func1;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Pac4j shared store implementation based on vert.x clustered shared data.
*/
public class VertxClusteredMapStore<K, V> extends VertxMapStoreBase implements Store<K, V> {
private final Vertx rxVertx;
private final int blockingTimeoutSeconds;
public VertxClusteredMapStore(final io.vertx.core.Vertx vertx) {
this(vertx, 1);
}
public VertxClusteredMapStore(final io.vertx.core.Vertx vertx, final int timeoutSeconds) {
rxVertx = Vertx.newInstance(vertx);
blockingTimeoutSeconds = timeoutSeconds;
}
@Override
public V get(K key) {
voidAsyncOpToBlocking(map -> map.getObservable((key)));
final CompletableFuture<V> valueFuture = new CompletableFuture<>();
rxVertx.sharedData().<K, V>getClusterWideMapObservable(PAC4J_SHARED_DATA_KEY)
.flatMap(map -> map.getObservable(key))
.subscribe(valueFuture::complete);
try {
return valueFuture.get(blockingTimeoutSeconds, TimeUnit.SECONDS);
} catch (InterruptedException|ExecutionException|TimeoutException e) {
throw new TechnicalException(e);
}
}
@Override
public void set(K key, V value) {
voidAsyncOpToBlocking(map -> map.putObservable(key, value));
}
@Override
public void remove(K key) {
voidAsyncOpToBlocking(map -> map.removeObservable(key));
}
public void voidAsyncOpToBlocking(Func1<AsyncMap, Observable> asyncOp) {
CompletableFuture<Void> future = new CompletableFuture<>();
rxVertx.sharedData().getClusterWideMapObservable(PAC4J_SHARED_DATA_KEY)
.map(asyncOp)
.subscribe(result -> future.complete(null));
try {
future.get(blockingTimeoutSeconds, TimeUnit.SECONDS);
} catch (InterruptedException|ExecutionException |TimeoutException e) {
throw new TechnicalException(e);
}
}
}